Conversation
Jobs are configured as named resources (DATABRICKS_JOB_<KEY> env vars)
and discovered at startup, following the files plugin pattern.
API is scoped to configured jobs:
appkit.jobs('etl').runNow()
appkit.jobs('etl').runNowAndWait()
appkit.jobs('etl').lastRun()
appkit.jobs('etl').listRuns()
appkit.jobs('etl').asUser(req).runNow()
Single-job shorthand via DATABRICKS_JOB_ID env var.
Supports OBO access via asUser(req).
Co-authored-by: Isaac
Signed-off-by: Evgenii Kniazev <evgenii.kniazev@databricks.com>
There was a problem hiding this comment.
Pull request overview
Adds a new resource-scoped “jobs” plugin to @databricks/appkit, following the existing “files” plugin pattern: jobs are discovered from environment variables at startup and exposed via a keyed accessor API, with HTTP routes for triggering and monitoring runs.
Changes:
- Introduces
plugins/jobs(manifest, defaults, params mapping, types, plugin implementation, and extensive tests). - Adds
connectors/jobswith telemetry + cancellation support and updates exports/docs to surface the new plugin and types. - Updates templates and generated API docs/sidebars to include the new Jobs plugin.
Reviewed changes
Copilot reviewed 24 out of 25 changed files in this pull request and generated 7 comments.
Show a summary per file
| File | Description |
|---|---|
| template/appkit.plugins.json | Adds “jobs” to plugin template metadata + resource description. |
| pnpm-lock.yaml | Locks new dependency (zod@4.3.6) and related lockfile updates. |
| packages/appkit/src/plugins/jobs/types.ts | Public types for Jobs plugin API/config (JobAPI/JobHandle/IJobsConfig). |
| packages/appkit/src/plugins/jobs/plugin.ts | Core JobsPlugin: env discovery, dynamic resource requirements, API methods, HTTP routes. |
| packages/appkit/src/plugins/jobs/params.ts | TaskType-based param mapping into SDK request fields. |
| packages/appkit/src/plugins/jobs/defaults.ts | Execution defaults for read/write/stream operations. |
| packages/appkit/src/plugins/jobs/manifest.json | Plugin manifest + config schema + baseline resource definition. |
| packages/appkit/src/plugins/jobs/index.ts | Barrel exports for Jobs plugin/types. |
| packages/appkit/src/plugins/jobs/tests/plugin.test.ts | Comprehensive unit tests for discovery, API, routes, and validation. |
| packages/appkit/src/plugins/index.ts | Exposes jobs from the plugins barrel. |
| packages/appkit/src/index.ts | Exposes jobs and related public types/configs from package root. |
| packages/appkit/src/connectors/jobs/client.ts | JobsConnector SDK wrapper with telemetry instrumentation + limit handling. |
| packages/appkit/src/connectors/jobs/types.ts | Connector config type (timeout/telemetry). |
| packages/appkit/src/connectors/jobs/index.ts | Connector barrel exports. |
| packages/appkit/src/connectors/index.ts | Exposes jobs connector from connectors barrel. |
| packages/appkit/package.json | Adds zod dependency for runtime param schemas + JSON schema generation. |
| docs/docs/api/appkit/typedoc-sidebar.ts | Adds new Jobs docs entries to sidebar. |
| docs/docs/api/appkit/*.md | Adds generated API docs pages for Jobs plugin types. |
| docs/docs/api/appkit/index.md | Adds Jobs-related types to API index list. |
| docs/docs/api/appkit/Interface.BasePluginConfig.md | Updates “Extended by” list to include IJobsConfig. |
Files not reviewed (1)
- pnpm-lock.yaml: Language not supported
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
|
How it is different from @keugenek PR here: #221? If you based on top of Evgenii's work, maybe it's worth to recognize his contribution? What I'm thinking is either:
WDYT? |
I got stuck trying to update his PR because it was opened from a fork, it's noted in the PR description:
So, I couldn't get a clean CI to merge it, and if I merged to It's also marked as a comment on the original PR |
It wouldn't trigger a release currently (finalizing releases is manual) so there shouldn't be a problem with that 👍 but I'd wait until your PR (on top of this one) is ready to merge, and I'd merge both one after another. What do you think? |
…for jobs plugin Signed-off-by: Atila Fassina <atila@fassina.eu>
493146a to
791b146
Compare
040f7bd to
d8133b9
Compare
MarioCadenas
left a comment
There was a problem hiding this comment.
I added some comments, but I'm actually wondering if this should just be a "jobs" plugin or if we should extend this and make it support both jobs and pipelines tbh 😅
| } | ||
|
|
||
| /** | ||
| * @internal |
There was a problem hiding this comment.
this shouldn't be internal no?
| */ | ||
| export const jobs = toPlugin(JobsPlugin); | ||
|
|
||
| export { JobsPlugin }; |
There was a problem hiding this comment.
why do we need to export this? tests?
| method: "post", | ||
| path: "/:jobKey/run", | ||
| handler: async (req: express.Request, res: express.Response) => { | ||
| const { jobKey } = this._resolveJob(req, res); |
There was a problem hiding this comment.
can we maybe simplify this endpoint a little bit? it seems too long no?
| return result.ok ? result : errorResult(result.status); | ||
| }, | ||
|
|
||
| async *runAndWait( |
There was a problem hiding this comment.
can runAndWait be simplified? maybe we can extract some parts?
| const client = getWorkspaceClient(); | ||
| if (!client) { | ||
| throw new InitializationError( | ||
| "Jobs plugin requires a configured workspace client", | ||
| ); | ||
| } |
There was a problem hiding this comment.
do we need this check? I don't think its needed, at least no plugin is doing this check?
| "vite": "npm:rolldown-vite@7.1.14", | ||
| "ws": "8.18.3" | ||
| "ws": "8.18.3", | ||
| "zod": "^4.3.6" |
There was a problem hiding this comment.
pin the version to 4.3.6 please 😄
|
a few more things I noticed going through the core package: 1. in self._readSettings(["jobs:listRuns", jobKey, options ?? {}])when 2. in notebook_params: Object.fromEntries(
Object.entries(params).map(([k, v]) => [k, String(v)]),
),if someone passes an object or array through (e.g. with a loose zod schema like 3. polling in I know I already asked if we can simplify |
pkosiec
left a comment
There was a problem hiding this comment.
Just a few comments 👍 Nice work!
There was a problem hiding this comment.
Could you rebase the PR? The updated skill is on main: https://github.com/databricks/appkit/blob/main/.claude/skills/install-appkit-artifact.md
There was a problem hiding this comment.
Here's agentic review:
Code Review: Jobs Plugin for Databricks Lakeflow Jobs
Scope: ekniazev/jobs-plugin-core branch, 2 commits, ~39 files changed
Intent: Add a new resource-scoped Jobs plugin for Databricks Lakeflow Jobs with connector, plugin, HTTP routes, SSE streaming, param validation, OBO support, frontend page, docs, and tests. Also fixes StreamManager to abort generators on client disconnect.
P1 -- High
| # | File | Issue | Confidence |
|---|---|---|---|
| 1 | docs/docs/plugins/jobs.md:41 |
Docs/code mismatch: per-job field name. Docs table says timeout for per-job config, but the TypeScript field in types.ts:69 is waitTimeout. Users following the docs will set the wrong field. |
0.95 |
| 2 | jobs.route.tsx:95-100 |
SSE stream parsing doesn't handle split chunks. decoder.decode(value, { stream: true }) can split a data: line across two chunks. The code splits on \n and checks line.startsWith("data: "), so a line split mid-chunk would be silently dropped or corrupted. Should buffer incomplete lines between reads. |
0.85 |
P2 -- Moderate
| # | File | Issue | Confidence |
|---|---|---|---|
| 3 | jobs.route.tsx:255-256 |
React key collision on stream log. key={line} uses the line content as key. Duplicate SSE messages (heartbeats, repeated status like "RUNNING") will produce duplicate keys, causing React reconciliation issues and potential UI glitches. Use index-based key or prepend a counter. |
0.90 |
| 4 | plugin.ts:229-278 |
Duplicated param validation block. runNow (lines 229-245) and runAndWait (lines 268-283) contain identical validation + mapping logic. If validation rules change, both must be updated. Extract a shared _validateAndMapParams(jobKey, params) method. |
0.85 |
| 5 | connectors/jobs/client.ts:176 |
Semantic mismatch: ExecutionError.statementFailed. Used for generic Jobs API errors, but the name implies SQL statement failures. Other connectors (sql-warehouse) use it for actual SQL errors. While the error chain works technically, it's misleading for debugging/logging. |
0.75 |
P3 -- Low
| # | File | Issue | Confidence |
|---|---|---|---|
| 6 | plugin.ts:717 |
Unnecessary wrapper function. ((jobKey: string) => resolveJob(jobKey)) as JobsExport can be simplified to resolveJob as JobsExport. |
0.90 |
| 7 | jobs.route.tsx:23-24 |
TERMINATED mapped to green unconditionally. stateColor("TERMINATED") returns green, but TERMINATED only means the run ended -- it could have failed. The result_state column handles this separately, but the green lifecycle indicator is misleading when paired with a red result. |
0.70 |
| 8 | package.json (appkit) |
Zod caret range ^4.3.6. For a published SDK, pinned versions are safer to avoid unexpected breaks from minor Zod releases. The lockfile shows two Zod versions (4.1.13 + 4.3.6) coexisting. |
0.65 |
Coverage
- Tests: Comprehensive test suite (1712 lines) covering discovery, resource requirements, exports, parameter validation, interceptors, polling, error handling, OBO, route handlers, XSS sanitization.
- StreamManager fix: Includes a targeted test for the new abort-on-disconnect behavior.
- Testing gaps: No integration test for the full SSE streaming path (triggerRun -> poll -> client disconnect -> abort). Frontend component has no tests (acceptable for dev-playground).
Verdict: Ready with fixes. The docs/code mismatch (#1) and SSE parsing (#2) should be addressed before merge. Items #3-5 are recommended. Items #6-8 are at your discretion.
There was a problem hiding this comment.

Important
to maintain contribution history this PR should be rebased when merged
(don't merge it if it has more than 2 commits)
Summary
Resource-scoped jobs plugin following the files plugin pattern. Jobs are configured as named resources discovered from environment variables at startup.
Design
DATABRICKS_JOB_<KEY>env vars (e.g.DATABRICKS_JOB_ETL=123)DATABRICKS_JOB_IDmaps to the"default"keyCAN_MANAGE_RUNpermissiondatabricks apps init --features jobsAPI
Files changed
plugins/jobs/manifest.json— declares job resource withCAN_MANAGE_RUNpermissionplugins/jobs/types.ts—JobAPI,JobHandle,JobsExport,IJobsConfigtypesplugins/jobs/plugin.ts—JobsPluginwithdiscoverJobs(),getResourceRequirements(), resource-scopedcreateJobAPI()plugins/jobs/index.ts— barrel exportsconnectors/jobs/client.ts—listRunsnow respectslimitparameterplugins/jobs/tests/plugin.test.ts— 32 tests covering discovery, resource requirements, exports, OBO, multi-job, and auto-fillDocumentation safety checklist
demo
lakeflow-jobs.mp4